#pragma once
#include "Socket.hpp"
#include "Log.hpp"
#include "Inetaddr.hpp"
#include <poll.h>

namespace SelectModule
{
    using namespace SocketModule;
    using namespace LogModule;
    const int gdefualtfd = -1;
#define NUM sizeof(fd_set) * 8
    class PollServer
    {
    private:
        uint16_t _port;
        std::shared_ptr<Socket> _listensocket;
        bool _isrunning;
        struct pollfd _fd_array[NUM]; // 这里我直接给位定长的了，实际应该是是指针
        void Dispacher()
        {
            for (int i = 0; i < NUM; i++)
            {
                if (_fd_array[i].fd == gdefaultfd)
                    continue;

                if (_fd_array[i].fd == _listensocket->FD())
                {
                    // 进行acceptor
                    if (_fd_array[i].revents & POLLIN)
                        AccePtor();
                }
                else
                {
                    // 进行去取操作
                    if (_fd_array[i].revents & POLLIN)
                        ReadIo(i);
                }
            }
        }
        void AccePtor()
        {
            InetAddr client;
            int newfd = _listensocket->Acceptor(&client);
            LOG(LogLevel::INFO) << "get a newfd, newfd is :  " << newfd << " client info: " << client.Info();
            int pos = -1;
            for (int i = 0; i < NUM; i++)
            {
                if (_fd_array[i].fd == gdefaultfd)
                {
                    pos = i;
                    break;
                }
            }
            if (pos == -1)
            {
                LOG(LogLevel::INFO) << "辅助数组已满，无法关注新的连接";
                ::close(newfd); // 一定要关闭!!!!!
                return;
            }
            _fd_array[pos].fd = newfd;
            _fd_array[pos].events = POLLIN;
        }
        void ReadIo(int i)
        {
            char buffer[1024];
            int n = ::recv(_fd_array[i].fd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                LOG(LogLevel::INFO) << "client say# " << buffer;
                std::string message = "echo server# ";
                message += buffer;
                ::send(_fd_array[i].fd, message.c_str(), message.size(), 0);
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client quit: " << _fd_array[i].fd;
                ::close(_fd_array[i].fd);
                _fd_array[i].fd = gdefaultfd;
                _fd_array[i].events = _fd_array[i].revents = 0;
            }
            else
            {
                LOG(LogLevel::INFO) << "read error, fd is : " << _fd_array[i].fd;
                ::close(_fd_array[i].fd);
                _fd_array[i].fd = gdefaultfd;
                _fd_array[i].events = _fd_array[i].revents = 0;
            }
        }

    public:
        PollServer(uint16_t port) : _port(port), _listensocket(std::make_shared<TcpSocket>()), _isrunning(false)
        {
            _listensocket->BuildTckSocket(_port);
            for (int i = 0; i < NUM; i++)
            {
                _fd_array[i].fd = gdefaultfd;
                _fd_array[i].events = _fd_array[i].revents = 0;
            }
            //默认处理listensocket
            _fd_array[0].fd = _listensocket->FD();
            _fd_array[0].events = POLLIN;
        }
        void Loop()
        {
            _isrunning = true;
            int timeout = 1000;
            while (_isrunning)
            {
                int n = ::poll(_fd_array, NUM, timeout);
                switch (n)
                {
                case -1:
                    LOG(LogLevel::ERROR) << "读取失败,等待了错误的fd?";
                    break;
                case 0:
                    LOG(LogLevel::WARNING) << "time out";
                    break;
                default:
                    Dispacher();
                    break;
                }
            }
            _isrunning = false;
        }
        ~PollServer() {}
    };
}